package com.szq.lottery.config;

import com.szq.lottery.DBRouterConfig;
import com.szq.lottery.DBRouterJoinPoint;
import com.szq.lottery.dynamic.DynamicDataSource;
import com.szq.lottery.strategy.IDBRouterStrategy;
import com.szq.lottery.strategy.Impl.DBRouterStrategyHashCode;
import com.szq.lottery.util.PropertyUtil;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.EnvironmentAware;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.transaction.support.TransactionTemplate;

import javax.sql.DataSource;
import java.util.HashMap;
import java.util.Map;

/**
 * @author 吾空白
 * @description: 数据源配置解析
 */
@Configuration
public class DataSourceAutoConfig implements EnvironmentAware {

    /**
     * 数据源配置组
     */
    private Map<String,Map<String,Object>> dataSourceMap=new HashMap<>();

    /**
     * 默认数据源配置
     */
    private Map<String,Object> defaultDataSourceConfig;

    /**
     * 分库数量
     */
    private int dbCount;

    /**
     * 分表数量
     */
    private int tbCount;

    /**
     * 路由字段
     */
    private String routerKey;

    @Bean(name = "db-router-point")
    @ConditionalOnMissingBean
    public DBRouterJoinPoint point(DBRouterConfig dbRouterConfig, IDBRouterStrategy dbRouterStrategy) {
        return new DBRouterJoinPoint(dbRouterConfig, dbRouterStrategy);
    }


    @Bean
    public IDBRouterStrategy dbRouterStrategy(DBRouterConfig dbRouterConfig) {
        return new DBRouterStrategyHashCode(dbRouterConfig);
    }

    @Bean
    public DBRouterConfig dbRouterConfig() {
        return new DBRouterConfig(dbCount, tbCount, routerKey);
    }


    @Bean
    public TransactionTemplate transactionTemplate(DataSource dataSource) {
        DataSourceTransactionManager dataSourceTransactionManager = new DataSourceTransactionManager();
        dataSourceTransactionManager.setDataSource(dataSource);

        TransactionTemplate transactionTemplate = new TransactionTemplate();
        transactionTemplate.setTransactionManager(dataSourceTransactionManager);
        transactionTemplate.setPropagationBehaviorName("PROPAGATION_REQUIRED");
        return transactionTemplate;
    }


    @Bean
    public DataSource dataSource(){
        //创建数据源
        Map<Object,Object> targetDataSources=new HashMap<>();
        for (String dbInfo:dataSourceMap.keySet()){
            Map<String, Object> objectMap = dataSourceMap.get(dbInfo);
            targetDataSources.put(dbInfo,new DriverManagerDataSource(objectMap.get("url").toString(),
                    objectMap.get("username").toString(),objectMap.get("password").toString()));
        }
        //设置数据源
        DynamicDataSource dynamicDataSource = new DynamicDataSource();
        dynamicDataSource.setTargetDataSources(targetDataSources);
        dynamicDataSource.setDefaultTargetDataSource(new DriverManagerDataSource(defaultDataSourceConfig.get("url").toString(),
                defaultDataSourceConfig.get("username").toString(),defaultDataSourceConfig.get("password").toString()));

        return dynamicDataSource;
    }

    @Override
    public void setEnvironment(Environment environment) {
        String prefix="min-db-router.jdbc.datasource";
        dbCount=Integer.valueOf(environment.getProperty(prefix+"dbCount"));
        tbCount=Integer.valueOf(environment.getProperty(prefix+"tbCount"));
        routerKey=environment.getProperty(prefix+"routerKey");

        //分库分表数据源
        String dataSources=environment.getProperty(prefix+"list");
        assert dataSources!=null;
        for (String dbInfo : dataSources.split(",")){
            Map<String,Object> dataSourceProps = PropertyUtil.handle(environment, prefix + dbInfo, Map.class);
            dataSourceMap.put(dbInfo,dataSourceProps);
        }
        //默认数据源
        String defaultData=environment.getProperty(prefix+"default");
        defaultDataSourceConfig=PropertyUtil.handle(environment,prefix+defaultData,Map.class);
    }
}
